package com.example.skillcinema.db.repositories

import android.adservices.adid.AdId
import com.example.skillcinema.db.apis.RetrofitService
import com.example.skillcinema.db.displaymodels.FilmDisplayModel
import com.example.skillcinema.db.enums.FilmTypes
import com.example.skillcinema.db.localdb.ApplicationDataBase
import com.example.skillcinema.db.localdb.daos.FilmDao
import com.example.skillcinema.db.localdb.tables.CollectionEntity
import com.example.skillcinema.db.localdb.tables.FilmCollectionCrossRef
import com.example.skillcinema.db.localdb.tables.FilmEntity
import com.example.skillcinema.db.models.Film
import kotlinx.coroutines.delay
import retrofit2.Retrofit
import javax.inject.Inject
import javax.inject.Singleton

open class BaseRepository @Inject constructor(val db: ApplicationDataBase) {
    fun convertToFilmDto(
        id: Int,
        imageUrl: String,
        rate: Float,
        name: String,
        genre: String,
        filmType: String,
        isWatched: Boolean
    ): FilmDisplayModel =
        FilmDisplayModel(id, imageUrl, rate, name, genre, FilmTypes.valueOf(filmType), isWatched)

    suspend fun getFilmById(id: Int): FilmDisplayModel {
        delay(250)
        val film: Film = RetrofitService.filmsApi.getById(id)
        val localFilm: FilmEntity? =
            db.filmDao().getFilmsByCollectionType(CollectionEntity.CollectionType.WATCHED).find {
                it.filmId == film.kinopoiskId
            }
        return convertToFilmDto(
            film.kinopoiskId,
            film.posterUrl,
            film.ratingKinopoisk ?: 0.0f,
            film.nameRu ?: (film.nameEn ?: "[No name]"),
            film.genres.joinToString(", ") { it -> it.genre },
            film.type,
            localFilm != null
        )
    }

    suspend fun getFilmCollections(filmId: Int): List<FilmCollectionCrossRef> {
        return db.filmCollectionCrossRefDao().getFilmCollections(filmId)
    }

    suspend fun addFilmToCollection(film: FilmEntity, collectionId: Int) {
        addFilm(film)
        db.filmCollectionCrossRefDao()
            .addFilmToCollection(FilmCollectionCrossRef(film.filmId, collectionId))
    }

    suspend fun addFilm(film: FilmEntity) {
        val filmExistence: FilmEntity? = db.filmDao().getFilmById(film.filmId)
        if (filmExistence == null) db.filmDao().insertFilm(film)
    }

    suspend fun removeFilmFromCollection(filmId: Int, collectionId: Int): Unit =
        db.filmCollectionCrossRefDao()
            .removeFilmFromCollection(FilmCollectionCrossRef(filmId, collectionId))

    suspend fun getCollections(): List<CollectionEntity> = db.collectionDao().getAllCollections()

    suspend fun createCollection(collection: CollectionEntity): Int {
        db.collectionDao().insertCollection(collection)
        return db.collectionDao().getCollectionByName(collection.name)?.collectionId ?: 0
    }

    suspend fun getCollectionFilms(collection: CollectionEntity): List<FilmEntity> =
        db.filmCollectionCrossRefDao().getFilmsByCollectionId(collection.collectionId)

    companion object {
        const val PREVIEW_ITEMS_COUNT: Int = 20
        const val FIRST_PAGE = 1
    }
}